#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include<sys/wait.h>
#include<cstdio>
#include<cstring>

void ChildWrite(int wfd)
{
    char buffer[1024];
    int cnt = 0;
    while(true)
    {
//注：接口是C语言的处理字符串的，几乎都会自动加上 \0 
//但是  系统调用属于接口下层   不关心字符串  默认就是 \0结尾  可以用strlen
        //用C接口对内容进行格式化
        snprintf(buffer,sizeof(buffer),"I am child,pid: %d,cnt: %d",getpid(),cnt++);
        write(wfd,buffer,strlen(buffer));    //内容写进管道中   这里直接使用strlen  就不写\0 
        // sleep(1);          //一秒写一个
        
    //这是测试写完一次就退出（* 结合下面 *）
        // printf("child:%d\n",cnt);
        // sleep(2);
        // break;

    //这是测试一直写   父进程读取一条消息就退出
        printf("child :%d\n",cnt);
        sleep(2);
        }
}

void FatherRead(int rfd)
{
    char buffer[1024];
    while(true)
    {
        buffer[0]=0;    //每次开始都把buffer全部置为0
        ssize_t n =read(rfd,buffer,sizeof(buffer)-1);    //但是这里需要自己修改一下   
    //参数二：读取的起始地址    参数三：表示期望读取多少字节     n是实际读的
        if(n > 0)    //n > 0 表示读取成功
        {
            buffer[n] = 0;   //转为字符串
            std::cout<<"child say: "<<buffer<<std::endl;
        }
        // sleep(5);
        
        else
        {
            //测试写完一次就退出（* 结合上面 *）
            // std::cout<<"n : "<< n <<std::endl;
            
            //测试一直写  不读（结合上面）
            break;            
        }
        break;      //这条也是测试一直写的修改点
    }
}

int main()
{
    // 步骤1.创建管道
    int fds[2] = {0};      //fds[0]对应读端     fds[1]对应写端
    int n = pipe(fds);
    if (n < 0)
    {
        std::cerr << "pipe error" << std::endl;
        return 1;
    }
    std::cout << "fds[0]" << fds[0] << std::endl;
    std::cout << "fds[1]" << fds[1] << std::endl;

    // 步骤2.创建子进程
    pid_t id = fork();
    if (id == 0)
    {
        //这是子进程
        //操作code
        //子进程是写  关闭不需要的
        close(fds[0]);     //关闭读端   因为子进程是写
        ChildWrite(fds[1]);
        close(fds[1]);
        exit(0);
    }

    // 步骤3.关闭不需要的读写端，形成通信信道
    // 父进程 读 r           子进程 写 w
    close(fds[1]);   //父进程是  读端  关闭1
    FatherRead(fds[0]);    //读取应该在wait之前   因为（应该在活跃期间进行）
    // waitpid(id,nullptr,0);         //头文件  #include<sys/wait.h>
    // close(fds[0]);



    //测试一直写  不读（结合上面）
    close(fds[0]);
    sleep(3);      //不让父进程着急回收  进行睡眠3s
    int status = 0; 
    int ret = waitpid(id,&status,0);
    if(ret > 0)
    {
        printf("exit code:%d,exit signal:%d\n",(status>>8) & 0xFF,status & 0x7F);
        sleep(3);
    }
    
    return 0;
}